/*
 * Copyright (c) 2009, Servoy-stuff
 * 
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 * 
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 * http://www.fsf.org/licensing/licenses/lgpl.txt
 */
package net.stuff.servoy.beans.slider.swing;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Hashtable;

import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import net.stuff.servoy.beans.slider.IServoySliderBean;
import net.stuff.servoy.beans.slider.ServoyUtils;


import com.servoy.j2db.Messages;
import com.servoy.j2db.dataprocessing.IFoundSet;
import com.servoy.j2db.dataprocessing.IRecord;
import com.servoy.j2db.plugins.IClientPluginAccess;
import com.servoy.j2db.scripting.IScriptObject;
import com.servoy.j2db.util.ComponentFactoryHelper;
import com.servoy.j2db.util.Debug;
import com.servoy.j2db.util.PersistHelper;

/**
 * ServoySlider bean v4 - added simple wicket implementation
 * @author Servoy Stuff
 * http://www.servoy-stuff.net/
 */
public class ServoySwingSlider extends JSlider implements IServoySliderBean, ChangeListener, IScriptObject, PropertyChangeListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	protected IFoundSet currentFoundset;
	protected IRecord currentRecord;
	protected boolean validationEnabled = true;
	protected boolean ignoreUpdate = true;
	
	private String dataProviderID;
	private String toolTipMessage;
	
	private int majorTicks = 50;
	private int minorTicks = 10;
	private int minimumValue = 0;
	private int maximumValue = 100;
	private int currentValue = 0;
	
	private int precision = 2;
	private boolean usingDecimals;
	private String webStyleType;
	private IClientPluginAccess app;
	
	private String onDataChange;
	private Number previousValue = 0;
	
	public ServoySwingSlider() {
		super();
		addChangeListener(this);
		addPropertyChangeListener(this);
	}
	
	/* (non-Javadoc)
	 * @see com.servoy.j2db.dataui.IServoyAwareBean#initialize(com.servoy.j2db.plugins.IClientPluginAccess)
	 */
	public void initialize(IClientPluginAccess app) {
		this.app = app;
	}

	/* (non-Javadoc)
	 * @see com.servoy.j2db.dataui.IServoyAwareBean#setSelectedRecord(com.servoy.j2db.dataprocessing.IRecord)
	 */
	public void setSelectedRecord(IRecord record) {
		if (record != null) {
			this.currentFoundset = record.getParentFoundSet();
			this.currentRecord = record;
			updateSlider();
		}
	}

	/**
	 * Updates the slider from the values of the current Foundset, or dataprovider
	 */
	private void updateSlider() {
		if (ServoyUtils.isExisting(currentFoundset, currentRecord)) {
			if (ServoyUtils.isContainedInFoundset(currentRecord,getDataProviderID())) {
				Object obj = currentRecord.getValue(getDataProviderID());
				if (obj != null && obj instanceof Number) {
					setSliderValue((Number)obj);
				} else {
					setSliderValue(getMinimumValue());
				}
			} else {
				// the behaviour we had before:
				if (validationEnabled) {
					setMinimumValue(1);
					int max = currentFoundset.getSize();
					setMaximumValue(max);
					setMajorTicks(max-1);
					int tickSpacing = Math.max(Math.round(max/10),1);
					setMinorTicks(tickSpacing);
					setSliderValue(currentFoundset.getSelectedIndex()+1);
					updateLabels(); // added to update when used as navigation bean
				} else {
					setMinimumValue(0);
					setSliderValue(0);
				}
			}
		}
	}
	
	/**
	 * Set the slider value without firing the stateChanged() method
	 * and check for usage of a precision factor to use
	 * @param x Number
	 */
	private void setSliderValue(Number x) {
		ignoreUpdate = true;
		previousValue = x;
		if (isUsingFactor()) {
			setDoubleValue(x.doubleValue());
		} else {
			setValue(x.intValue());
		}
	}
	
	
	/* (non-Javadoc)
	 * @see com.servoy.j2db.dataprocessing.IDisplay#isReadOnly()
	 */
	public boolean isReadOnly() {
		return false;
	}

	/* (non-Javadoc)
	 * @see com.servoy.j2db.dataprocessing.IDisplay#setValidationEnabled(boolean)
	 */
	public void setValidationEnabled(boolean paramBoolean) {
		this.validationEnabled = paramBoolean;
		if (!hasDataProvider()) {
			setEnabled(paramBoolean);
		}
	}

	/* (non-Javadoc)
	 * @see com.servoy.j2db.dataprocessing.IDisplay#stopUIEditing(boolean)
	 */
	public boolean stopUIEditing(boolean paramBoolean) {
		return true;
	}


	/* (non-Javadoc)
	 * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent)
	 */
	public void stateChanged(ChangeEvent e) {
		if (getValueIsAdjusting()) {
			if (app != null) {
				if (ServoyUtils.isContainedInFoundset(currentRecord, getDataProviderID())) {
					if (isUsingFactor()) {
						app.setStatusText(""+getNumberValue());
					} else {
						app.setStatusText(""+getValue());
					}
				} else {
					app.setStatusText(""+(getValue()-1));
				}
			}
		} else {
			if (!ignoreUpdate && ServoyUtils.isExisting(currentFoundset, currentRecord)) {
				Number newValue = null;
				Number previous = previousValue;
				if (ServoyUtils.isContainedInFoundset(currentRecord, getDataProviderID())) {
					if (currentRecord.startEditing()) {
						if (isUsingFactor()) {
							newValue = getNumberValue();
							currentRecord.setValue(getDataProviderID(), newValue);
						} else {
							newValue = getValue();
							currentRecord.setValue(getDataProviderID(), newValue);
						}
					}
				} else {
					previous = currentFoundset.getSelectedIndex() + 1;
					newValue = getValue();
					currentFoundset.setSelectedIndex(getValue()-1);
				}
				if (ServoyUtils.isNotEmpty(onDataChange) 
						&& !ServoyUtils.numberEquals(previous, newValue)) {
					Debug.log("before: "+previous + " - after: "+newValue);
					ServoyUtils.runFunctionByName(onDataChange, app, new Object[] {previous, newValue});
				}
				previousValue = newValue;
				if (app != null) {
					app.setStatusText("Done");
				}
			}
		}
		ignoreUpdate = false;
	}

	/* (non-Javadoc)
	 * @see com.servoy.j2db.scripting.IScriptObject#getAllReturnedTypes()
	 */
	public Class[] getAllReturnedTypes() {
		return null;
	}

	/* (non-Javadoc)
	 * @see com.servoy.j2db.scripting.IScriptObject#getParameterNames(java.lang.String)
	 */
	public String[] getParameterNames(String methodName) {
		if ("setLocation".equals(methodName)) {
			return new String[] {"x", "y"};
		} else if ("setSize".equals(methodName)) {
			return new String[] {"width", "height"};
		} else if ("setBorder".equals(methodName)) {
			return new String[] {"border"};
		} else if ("setFont".equals(methodName)) {
			return new String[] {"font"};
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see com.servoy.j2db.scripting.IScriptObject#getSample(java.lang.String)
	 */
	public String getSample(String methodName) {
		StringBuffer buff = new StringBuffer();
		String tooltip = getToolTipFor(methodName);
		if (tooltip != null) {
			buff.append("//");
			buff.append(tooltip);
			buff.append("\n");
			if ("bgcolor".equals(methodName)) {
				buff.append("\tvar currentbg = %%elementName%%.bgcolor;\n");
				buff.append("\t%%elementName%%.bgcolor = currentbg;");
			} else if ("fgcolor".equals(methodName)) {
				buff.append("\tvar currentfg = %%elementName%%.fgcolor;\n");
				buff.append("\t%%elementName%%.fgcolor = currentfg;");
			} else if ("focusable".equals(methodName)) {
				buff.append("\tvar focusableState = %%elementName%%.focusable;\n");
				buff.append("\t%%elementName%%.focusable = !focusableState;");
			} else if ("inverted".equals(methodName)) {
				buff.append("\tvar currentInvertState = %%elementName%%.inverted;\n");
				buff.append("\t%%elementName%%.inverted = !currentInvertState;");
			} else if ("enabled".equals(methodName)) {
				buff.append("\tvar enabledState = %%elementName%%.enabled;\n");
				buff.append("\t%%elementName%%.enabled = !enabledState;");
			} else if ("visible".equals(methodName)) {
				buff.append("\tvar visibleState = %%elementName%%.visible;\n");
				buff.append("\t%%elementName%%.visible = !visibleState;");	
			} else if ("snapToTicks".equals(methodName)) {
				buff.append("\tvar snapToTicksState = %%elementName%%.snapToTicks;\n");
				buff.append("\t%%elementName%%.snapToTicks = !snapToTicksState;");	
			} else if ("majorTickSpacing".equals(methodName) ||
					"minorTickSpacing".equals(methodName) || 
					"minimum".equals(methodName) ||
					"maximum".equals(methodName)) {
				buff.append("\t//set the slider extent to 0-100 with major ticks every 20 and major ticks every 10/\n");
				buff.append("\t%%elementName%%.minimum = 0;\n");
				buff.append("\t%%elementName%%.maximum = 100;\n");
				buff.append("\t%%elementName%%.majorTickSpacing = 20;\n");
				buff.append("\t%%elementName%%.minorTickSpacing = 10;");
			} else if ("opaque".equals(methodName)) {
				buff.append("\tvar currentState = %%elementName%%.opaque;\n");
				buff.append("\t%%elementName%%.opaque = !currentState;");
			} else if ("value".equals(methodName)) {
				buff.append("\t%%elementName%%.value = 1;\n");
				buff.append("\tvar current = %%elementName%%.value;");
			} else if ("paintTicks".equals(methodName) ||
					"paintLabels".equals(methodName) ||
					"paintTrack".equals(methodName)) {
				buff.append("\tvar ticks = %%elementName%%.paintTicks;\n");
				buff.append("\tvar labels = %%elementName%%.paintLabels;\n");
				buff.append("\tvar track = %%elementName%%.paintTrack;\n");
				buff.append("\tvar showAll = (ticks && labels && track);\n");
			} else if ("orientation".equals(methodName)) {
				buff.append("\tvar orientation = %%elementName%%.orientation;\n");
				buff.append("\t%%elementName%%.orientation = 1; // = vertical");
			} else if ("precisionFactor".equals(methodName)) {
				buff.append("\tvar percentFactor = %%elementName%%.precisionFactor;\n");
				buff.append("\t%%elementName%%.percentFactor = 3; (3 decimals)");
			} else if ("usingDecimals".equals(methodName)) {
				buff.append("\tvar useDecimals = %%elementName%%.usingDecimals;\n");
				buff.append("\t%%elementName%%.usingDecimals = !useDecimals;");
			} else if ("toolTipText".equals(methodName)) {
				buff.append("\tvar tipText = %%elementName%%.toolTipText;\n");
				buff.append("\t%%elementName%%.toolTipText = current;");
			} else if ("getWidth".equals(methodName) ||
					"getHeight".equals(methodName) ||
					"setSize".equals(methodName)) {
				buff.append("\tvar w = %%elementName%%.getWidth();\n");
				buff.append("\tvar h = %%elementName%%.getHeight();\n");
				buff.append("\t//set the new size\n");
				buff.append("\t%%elementName%%.setSize(w,h);");
			} else if ("getName".equals(methodName)) {
				buff.append("\tvar name = %%elementName%%.getName();");
			} else if ("setBorder".equals(methodName)) {
				buff.append("\t%%elementName%%.setBorder('LineBorder,1,#ccffcc');");
			} else if ("setFont".equals(methodName)) {
				buff.append("\t%%elementName%%.setFont('Tahoma,1,11');");
			} else if ("setSize".equals(methodName)) {
				buff.append("\t%%elementName%%.setSize(200,40);");
			} else if ("getLocationX".equals(methodName)) {
				buff.append("\tvar x = %%elementName%%.getLocationX();");
			} else if ("getLocationY".equals(methodName)) {
				buff.append("\tvar y = %%elementName%%.getLocationY();");
			}
			buff.append("\n\t");
			return buff.toString();
		}
		return null;
	}

	/**
	 * Utility method to return different tooltip depending on method name
	 * @param methodName
	 * @return
	 */
	private String getToolTipFor(String methodName) {
		if ("getWidth".equals(methodName) ||
				"getHeight".equals(methodName) ||
				"setSize".equals(methodName)) {
			return "Returns the width/height";
		} else if ("setBorder".equals(methodName)) {
			return "Set the border attributes, must be the same as borderType string from Element Properties";
		} else if ("setFont".equals(methodName)) {
			return "Set the font 'fontname,style,size',  style = (plain=0, bold=1, italic=2, bold-italic=3)";
		}
		return getToolTip(methodName);
	}

	/* (non-Javadoc)
	 * @see com.servoy.j2db.scripting.IScriptObject#getToolTip(java.lang.String)
	 */
	public String getToolTip(String methodName) {
		if ("bgcolor".equals(methodName)) {
			return "Set / Get the background color"; 
		} else if ("fgcolor".equals(methodName)) {
			return "Set / Get the foreground color"; 
		} else if ("enabled".equals(methodName)) {
			return "Set / Get the enabled state (also called 'grayed')"; 
		} else if ("visible".equals(methodName)) {
			return "Set / Get the visiblity";
		} else if ("inverted".equals(methodName)) {
			return "Set / Get the inverted state";
		} else if ("orientation".equals(methodName)) {
			return "Set / Get the orientation - 0 = horizontal / 1 = vertical";
		} else if ("majorTickSpacing".equals(methodName)) {
			return "Set / Get the majorTickSpacing";
		} else if ("minorTickSpacing".equals(methodName)) {
			return "Set / Get the minorTickSpacing";
		} else if ("minimum".equals(methodName)) {
			return "Set / Get the minimum value";
		} else if ("maximum".equals(methodName)) {
			return "Set / Get the maximum value";
		} else if ("getLocationX".equals(methodName)) {
			return "Returns the X location";
		} else if ("getLocationY".equals(methodName)) {
			return "Returns the Y location";
		} else if ("setLocation".equals(methodName)) {
			return "Set the location";
		} else if ("getWidth".equals(methodName)) {
			return "Returns the width";
		} else if ("getHeight".equals(methodName)) {
			return "Returns the height";
		} else if ("setSize".equals(methodName)) {
			return "Set the size";
		} else if ("getName".equals(methodName)) {
			return "Get the element name";
		} else if ("setBorder".equals(methodName)) {
			return "Set the border";
		} else if ("toolTipText".equals(methodName)) {
			return "Set / Get the toolTipText (when hovering over with mouse)";
		} else if ("opaque".equals(methodName)) {
			return "Set / Get the transparency";
		} else if ("setFont".equals(methodName)) {
			return "Set the font";
		} else if ("focusable".equals(methodName)) {
			return "Set / Get the focusable state";
		} else if ("snapToTicks".equals(methodName)) {
			return "Set / Get the snapToTicks state";
		} else if ("paintTicks".equals(methodName) || 
				"paintLabels".equals(methodName) ||
				"paintTrack".equals(methodName)) {
			return "Show / Hide the ticks/labels/track";
		} else if ("value".equals(methodName)) {
			return "Set / Get the value of the slider";
		} else if ("precisionFactor".equals(methodName)) {
			return "Set / Get the precision factor (number of decimals)";
		} else if ("usingDecimals".equals(methodName)) {
			return "Set / get the usingDecimals flag";
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see com.servoy.j2db.scripting.IScriptObject#isDeprecated(java.lang.String)
	 */
	public boolean isDeprecated(String methodName) {
		return false;
	}

	
	public void js_setBgcolor(String paramString) {
		setBackground(PersistHelper.createColor(paramString));
	}
	public String js_getBgcolor() {
		return (getBackground() == null) ? null : PersistHelper.createColorString(getBackground());
	}
	public void js_setFgcolor(String paramString) {
		setForeground(PersistHelper.createColor(paramString));
	}
	public String js_getFgcolor() {
		return (getForeground() == null) ? null : PersistHelper.createColorString(getForeground());
	}
	public void js_setBorder(String paramString) {
		setBorder(ComponentFactoryHelper.createBorder(paramString));
	}
	public void js_setFont(String paramString) {
		if (paramString != null) {
			setFont(PersistHelper.createFont(paramString));
		}
	}
	public void js_setFocusable(boolean focusable) {
		setFocusable(focusable);
	}
	public boolean js_isFocusable() {
		return isFocusable();
	}
	public void js_setInverted(boolean inverted) {
		setInverted(inverted);
	}
	public boolean js_isInverted() {
		return getInverted();
	}
	public void js_setMajorTickSpacing(int majorTickSpacing) {
		setMajorTicks(majorTickSpacing);
	}
	public int js_getMajorTickSpacing() {
		return getMajorTicks();
	}
	public void js_setMaximum(int maximum) {
		setMaximumValue(maximum);
	}
	public int js_getMaximum() {
		return getMaximumValue();
	}
	public void js_setMinimum(int minimum) {
		setMinimumValue(minimum);
	}
	public int js_getMinimum() {
		return getMinimumValue();
	}
	public void js_setMinorTickSpacing(int minorTickSpacing) {
		setMinorTicks(minorTickSpacing);
	}
	public int js_getMinorTickSpacing() {
		return getMinorTicks();
	}
	public void js_setOpaque(boolean opaque) {
		setOpaque(opaque);
	}
	public boolean js_isOpaque() {
		return isOpaque();
	}
	public void js_setOrientation(int orientation) {
		setOrientation(orientation);
	}
	public int js_getOrientation() {
		return getOrientation();
	}
	public void js_setPaintLabels(boolean paintLabels) {
		setPaintLabels(paintLabels);
	}
	public boolean js_getPaintLabels() {
		return getPaintLabels();
	}
	public void js_setPaintTicks(boolean paintTicks) {
		setPaintTicks(paintTicks);
	}
	public boolean js_getPaintTicks() {
		return getPaintTicks();
	}
	public void js_setPaintTrack(boolean paintTrack) {
		setPaintTrack(paintTrack);
	}
	public boolean js_getPaintTrack() {
		return getPaintTrack();
	}
	public void js_setSnapToTicks(boolean snapToTicks) {
		setSnapToTicks(snapToTicks);
	}
	public boolean js_getSnapToTicks() {
		return getSnapToTicks();
	}
	public void js_setToolTipText(String toolTipText) {
		setToolTipText(toolTipText);
	}
	public String js_getToolTipText() {
		return getToolTipText();
	}
	public String js_getName() {
		return getName();
	}
	public void js_setLocation(int x, int y) {
		setLocation(x, y);
	}
	public void js_setSize(int width, int height) {
		setSize(width, height);
	}
	public void js_setValue(Number val) {
		if (isUsingFactor()) {
			setDoubleValue((val == null) ? getMinimumValue() : val.doubleValue());
		} else {
			setValue(val.intValue());
		}
	}
	public Number js_getValue() {
		if (isUsingFactor()) {
			return getNumberValue();
		} else {
			return getValue();
		}
	}
	public void js_setVisible(boolean visible) {
		setVisible(visible);
	}
	public boolean js_isVisible() {
		return isVisible();
	}
	public void js_setEnabled(boolean enabled) {
		setEnabled(enabled);
	}
	public boolean js_isEnabled() {
		return isEnabled();
	}
	public int js_getHeight() {
		return getHeight();
	}
	public int js_getWidth() {
		return getWidth();
	}
	public int js_getLocationX() {
		return getX();
	}
	public int js_getLocationY() {
		return getY();
	}
	
	public void js_setPrecisionFactor(int p) {
		setPrecision(p);
	}
	public int js_getPrecisionFactor() {
		return getPrecision();
	}
	public void js_setUsingDecimals(boolean newUsage) {
		setUsingDecimals(newUsage);
	}
	public boolean js_isUsingDecimals() {
		return isUsingDecimals();
	}

	
	/**
	 * @return the dataProviderID
	 */
	public String getDataProviderID() {
		return this.dataProviderID;
	}

	/**
	 * @param dataProviderID the dataProviderID to set
	 */
	public void setDataProviderID(String dataProviderID) {
		this.dataProviderID = dataProviderID;
	}
	
	private boolean hasDataProvider() {
		return ServoyUtils.isNotEmpty(getDataProviderID());
	}
	
	
	/**
	 * @return the toolTipMessage
	 */
	public String getToolTipMessage() {
		return toolTipMessage;
	}

	/**
	 * @param toolTipMessage the toolTipMessage to set
	 */
	public void setToolTipMessage(String toolTipMessage) {
		this.toolTipMessage = toolTipMessage;
		super.setToolTipText(Messages.getStringIfPrefix(toolTipMessage));
	}
	
	/**
	* returns the value with correct precision
	*/
	public Number getNumberValue() {
		NumberFormat formatter = NumberFormat.getNumberInstance();
		formatter.setMaximumFractionDigits(getPrecision());
		String s = formatter.format(getValue()/getPrecisionFactor());
		try {
			return formatter.parse(s);
		} catch (ParseException ex) {}
		return null;
	}
		
	/**
	 * @return true if is using decimals and a dataProviderID exists
	 */
	public boolean isUsingFactor() {
		return isUsingDecimals() && hasDataProvider();
	}

	/**
	 * @return the useDecimals
	 */
	public boolean isUsingDecimals() {
		return this.usingDecimals;
	}

	/**
	 * @param usingDecimals the useDecimals to set
	 */
	public void setUsingDecimals(boolean newUsage) {
		boolean usingDecimalsBefore = isUsingDecimals();
		this.usingDecimals = newUsage;
		if (usingDecimalsBefore != newUsage) {
			updateModel();
		}
	}

	/**
	 * Reset the values multiplied by the precision factor if needed
	 */
	protected void updateModel() {
		setMinimumValue(getMinimumValue());
		setMaximumValue(getMaximumValue());
		setMajorTicks(getMajorTicks());
		setMinorTicks(getMinorTicks());
		setCurrentValue(getCurrentValue());
		updateLabels();
	}

	/**
	 * @return the majorTicks
	 */
	public int getMajorTicks() {
		return majorTicks;
	}

	/**
	 * @param majorTicks the majorTicks to set
	 */
	public void setMajorTicks(int majorTicks) {
		if (majorTicks < 0) {
			majorTicks = 0;
		}
		this.majorTicks = majorTicks;
		if (isUsingFactor()) {
			setMajorTickSpacing(majorTicks * (int)Math.round(getPrecisionFactor()));
		} else {
			setMajorTickSpacing(majorTicks);
		}
	}

	/**
	 * @return the minorTicks
	 */
	public int getMinorTicks() {
		return minorTicks;
	}

	/**
	 * @param minorTicks the minorTicks to set
	 */
	public void setMinorTicks(int minorTicks) {
		if (minorTicks < 0) {
			minorTicks = 0;
		}
		this.minorTicks = minorTicks;
		if (isUsingFactor()) {
			setMinorTickSpacing(minorTicks * (int)Math.round(getPrecisionFactor()));
		} else {
			setMinorTickSpacing(minorTicks);
		}
	}

	/**
	 * @return the minimumValue
	 */
	public int getMinimumValue() {
		return minimumValue;
	}

	/**
	 * @param minimumValue the minimumValue to set
	 */
	public void setMinimumValue(int minimumValue) {
		if (!hasDataProvider()&& minimumValue < 0) {
			minimumValue = 0;
		}
		this.minimumValue = minimumValue;
		if (isUsingFactor()) {
			setMinimum((int)(minimumValue*getPrecisionFactor()));
		} else {
			setMinimum(minimumValue);
		}
	}

	/**
	 * @return the maximumValue
	 */
	public int getMaximumValue() {
		return maximumValue;
	}

	/**
	 * @param maximumValue the maximumValue to set
	 */
	public void setMaximumValue(int maximumValue) {
		if (!hasDataProvider()&& maximumValue < 1) {
			maximumValue = 1;
		}
		this.maximumValue = maximumValue;
		if (isUsingFactor()) {
			setMaximum((int)(maximumValue*getPrecisionFactor()));
		} else {
			setMaximum(maximumValue);
		}
	}

	/**
	 * @return the currentValue
	 */
	public int getCurrentValue() {
		return currentValue;
	}

	/**
	 * @param currentValue the currentValue to set
	 */
	public void setCurrentValue(int currentValue) {
		if (!hasDataProvider()&& currentValue < 0) {
			currentValue = 0;
		}
		this.currentValue = currentValue;
		if (isUsingFactor()) {
			setDoubleValue(currentValue);
		} else {
			setValue(currentValue);
		}
	}

	/**
	 * Set the sliders value from a double using the precision factor
	 * @param val double
	 */
	private void setDoubleValue(double val) {
		setValue((int)(val*getPrecisionFactor()));
	}

	/**
	 * @return the precision
	 */
	public int getPrecision() {
		return precision;
	}

	/**
	 * @param precision the precision to set
	 */
	public void setPrecision(int precision) {
		int currentPrecision = getPrecision();
		if (precision < 0) {
			precision = 0; // can't be negative!
		}
		this.precision = precision;
		if (currentPrecision != precision) {
			updateModel();
		}
	}
	
	/**
	 * @return the precisionFactor as a double
	 */
	public double getPrecisionFactor() {
		return Math.pow(10.0, getPrecision());
	}


	/**
	 * Updates the label table if needed
	 */
	private void updateLabels() {
		Hashtable<Integer, JLabel> table = (Hashtable)getLabelTable();
		if (table != null) {
			table.clear();
			int labelIndex = getMinimum();
			for ( ; labelIndex <= getMaximum(); labelIndex += getMajorTickSpacing() ) {
				int val = (isUsingFactor()) ? (int)Math.round(labelIndex/getPrecisionFactor()) : labelIndex;
				table.put( new Integer( labelIndex ), new JLabel( ""+val, JLabel.CENTER ) );
	        }
			if (labelIndex != getMaximum()) {
				int val = (isUsingFactor()) ? (int)Math.round(getMaximum()/getPrecisionFactor()) : getMaximum();
				table.put( new Integer( getMaximum() ), new JLabel( ""+val, JLabel.CENTER ) );				
			}
			setLabelTable(table);
		}
	}
	
	/* (non-Javadoc)
	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
	 */
	public void propertyChange(PropertyChangeEvent evt) {
		if (isUsingFactor() && getPaintLabels() && getMajorTicks() > 0) {
			String propertyName = evt.getPropertyName();
			if ("minimum".equals(propertyName) || "maximum".equals(propertyName) ||
					"majorTickSpacing".equals(propertyName)) {
				updateLabels();
			}
		}
	}

	/* (non-Javadoc)
	 * @see com.servoy.j2db.ui.IComponent#getId()
	 */
	public String getId() {
		return null;
	}

	/* (non-Javadoc)
	 * @see com.servoy.j2db.ui.IComponent#setComponentEnabled(boolean)
	 */
	public void setComponentEnabled(boolean enabled) {
		setEnabled(enabled);
	}

	/* (non-Javadoc)
	 * @see com.servoy.j2db.ui.IComponent#setComponentVisible(boolean)
	 */
	public void setComponentVisible(boolean visible) {
		setVisible(visible);
	}

	/**
	 * @return the webStyleType
	 */
	public String getWebStyleType() {
		return this.webStyleType;
	}

	/**
	 * @param webStyleType the webStyleType to set
	 */
	public void setWebStyleType(String webStyleType) {
		this.webStyleType = webStyleType;
	}

	/**
	 * @return the onDataChange
	 */
	public String getOnDataChange() {
		return this.onDataChange;
	}

	/**
	 * @param onDataChange the onDataChange to set
	 */
	public void setOnDataChange(String onDataChange) {
		this.onDataChange = onDataChange;
	}
	
	
}
